package com.mangospin.cfterm;

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

/**
 * Simple utility for accessing University of Waterloo's Coldfire servers via Telnet.
 * Lots of shortcuts to speed development.
 * 
 * Project page: http://code.google.com/p/cfterm/
 * Distributed under Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
 * 
 * (c) Copyright 2008 by Han Xu
 * 
 * @author Han Xu
 * @version 0.1.0
 */
public class CFTerm {
	
	private static final String PROG_TITLE = "CFTerm";
	private static final String CF_SERVER = "cf-server.uwaterloo.ca";
	private static final String DEFAULT_S19_NAME = "cfterm-default-s19";
	
	private JTextArea textArea;
	private JFrame frame;
	private PrintWriter out;
	
	public CFTerm(int port, boolean moveToRight) {
		createGUI(moveToRight);
		try {
			Socket socket = new Socket(CF_SERVER, port);
			new ReaderThread(socket.getInputStream()).start();
			out = new PrintWriter(socket.getOutputStream());
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private void createGUI(boolean moveToRight) {
		frame = new JFrame(PROG_TITLE);
		frame.setSize(600, 600);
		frame.setLayout(new BorderLayout());
		if (moveToRight)
			frame.setLocation(600,0);
		
		textArea = new JTextArea();
		textArea.setFont(new Font("Courier New", Font.PLAIN, 14));
		textArea.addKeyListener(new KeyListener() {

			/**
			 * When the user types something
			 */
			public void keyPressed(KeyEvent arg0) {
				if (((int) arg0.getKeyChar()) == 10) {
					// Force Carriage Return as well
					out.print((char) 13);
				}
				// filter non-char
				if (arg0.getKeyChar() != 65535) {
					out.print(arg0.getKeyChar());
					out.flush();
				}
			}

			public void keyReleased(KeyEvent arg0) {
			}

			public void keyTyped(KeyEvent arg0) {
			}
			
		});
		textArea.setEditable(false);
		
		JScrollPane pane = new JScrollPane(textArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		frame.add(pane, BorderLayout.CENTER);
		
		JMenuBar menuBar = new JMenuBar();
		JMenuItem item = new JMenuItem("Send File");
		item.addActionListener(new ActionListener() {
			/**
			 * Performed when the Send File button is clicked
			 */
			public void actionPerformed(ActionEvent arg0) {
				out.print("dl -p terminal\r\n");
				out.flush();
				JFileChooser chooser = new JFileChooser();
				
				// Load the default s19 path
				
				try {
					ObjectInputStream ois = new ObjectInputStream(new FileInputStream(DEFAULT_S19_NAME));
					String defPath = (String) ois.readObject();
					ois.close();
					chooser.setSelectedFile(new File(defPath));
				} catch (Exception e) {
				}

				if (chooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) {
					File file = chooser.getSelectedFile();
					try {
						ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(DEFAULT_S19_NAME));
						oos.writeObject(file.getAbsolutePath());
						oos.close();
					} catch (FileNotFoundException e1) {
						e1.printStackTrace();
					} catch (IOException e1) {
						e1.printStackTrace();
					}
					try {
						FileInputStream fis = new FileInputStream(file);
						byte b[] = new byte[1];
						while (fis.read(b) == 1) {
							out.print(new String(b));
						}
						fis.close();
						out.flush();
					} catch (FileNotFoundException e) {
						e.printStackTrace();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		});
		menuBar.add(item);
		
		// start of the GO Button
		item = new JMenuItem("Go!");
		item.addActionListener(new ActionListener() {
			/**
			 * Performed when the Send File button is clicked
			 */
			public void actionPerformed(ActionEvent arg0) {
				out.print("go 10100000\r\n");
				out.flush();
			}
		});
		menuBar.add(item);
		
		frame.add(menuBar, BorderLayout.NORTH);
		
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
	}
	
	class ReaderThread extends Thread {
		private InputStream in;
		public ReaderThread(InputStream in) {
			this.in = in;
		}
		@Override
		public void run() {
			byte b[] = new byte[1];
			StringBuilder buffer = new StringBuilder();
			try {
				while (in.read(b) == 1) {
					
					// Create an internal line by line buffer
					if (b[0] == 10) {
						// Parse each line for second serial port
						if (buffer.indexOf("Second Serial Port On Port:") > -1) {
							// Found now port
							final int port = Integer.parseInt(buffer.substring(29).trim());
							// Wait a while before opening the new window
							new Thread() {
								@Override
								public void run() {
									try {
										sleep(500);
									} catch (InterruptedException e) {
										e.printStackTrace();
									}
									new CFTerm(port, true); //move to the right
									frame.toFront();
								}
							}.start();
						}
						buffer.setLength(0);
						
					} else {
						buffer.append(new String(b));
					}
					
					textArea.append(new String(b));
					textArea.setCaretPosition(textArea.getText().length());
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			JOptionPane.showMessageDialog(frame, "Remote disconnected (or other network error)");
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		System.out.println("CFTerm by Han Xu (http://code.google.com/p/cfterm/)");
		new CFTerm(23, false);
	}

}
